package cn.sunyblog.tool.threadpool.web;

import cn.sunyblog.tool.threadpool.DynamicThreadPoolExecutor;
import cn.sunyblog.tool.threadpool.monitor.ThreadPoolMetrics;
import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 动态线程池Web控制器
 * 提供线程池监控的Web界面和REST API
 * 
 * @author sunyblog
 */
@Controller
@RequestMapping("/threadpool")
@CrossOrigin(origins = "*", maxAge = 3600)
public class ThreadPoolWebController {
    
    // 存储线程池实例的映射
    private static final Map<String, DynamicThreadPoolExecutor> threadPoolMap = new ConcurrentHashMap<>();
    
    // 存储历史指标数据
    private static final Map<String, List<ThreadPoolMetrics>> metricsHistory = new ConcurrentHashMap<>();
    
    // 存储调整历史
    private static final Map<String, List<String>> adjustmentHistory = new ConcurrentHashMap<>();
    
    /**
     * 注册线程池实例
     */
    public static void registerThreadPool(String name, DynamicThreadPoolExecutor executor) {
        threadPoolMap.put(name, executor);
        metricsHistory.putIfAbsent(name, new ArrayList<>());
        adjustmentHistory.putIfAbsent(name, new ArrayList<>());
    }
    
    /**
     * 添加指标历史记录
     */
    public static void addMetricsHistory(String name, ThreadPoolMetrics metrics) {
        List<ThreadPoolMetrics> history = metricsHistory.get(name);
        if (history != null) {
            history.add(metrics);
            // 保留最近100条记录
            if (history.size() > 100) {
                history.remove(0);
            }
        }
    }
    
    /**
     * 添加调整历史记录
     */
    public static void addAdjustmentHistory(String name, String adjustment) {
        List<String> history = adjustmentHistory.get(name);
        if (history != null) {
            history.add(new Date() + ": " + adjustment);
            // 保留最近50条记录
            if (history.size() > 50) {
                history.remove(0);
            }
        }
    }
    
    /**
     * 主监控页面
     */
    @GetMapping("/monitor")
    public String monitorPage(Model model) {
        model.addAttribute("threadPools", threadPoolMap.keySet());
        return "threadpool/monitor";
    }
    
    /**
     * 获取线程池列表
     */
    @GetMapping("/api/pools")
    @ResponseBody
    @CrossOrigin(origins = "*")
    public Set<String> getThreadPools() {
        return threadPoolMap.keySet();
    }
    
    /**
     * 获取线程池当前状态
     */
    @GetMapping("/api/pools/{name}/status")
    @CrossOrigin(origins = "*")
    @ResponseBody
    public Map<String, Object> getThreadPoolStatus(@PathVariable String name) {
        DynamicThreadPoolExecutor executor = threadPoolMap.get(name);
        if (executor == null) {
            return Collections.singletonMap("error", "Thread pool not found: " + name);
        }
        
        ThreadPoolMetrics metrics = executor.getCurrentMetrics();
        Map<String, Object> status = new HashMap<>();
        status.put("name", name);
        status.put("metrics", metrics);
        status.put("adjustmentStats", executor.getAdjustmentStats());
        status.put("timestamp", new Date());
        
        return status;
    }
    
    /**
     * 获取线程池历史指标
     */
    @GetMapping("/api/pools/{name}/history")
    @ResponseBody
    @CrossOrigin(origins = "*")
    public List<ThreadPoolMetrics> getMetricsHistory(@PathVariable String name) {
        return metricsHistory.getOrDefault(name, new ArrayList<>());
    }
    
    /**
     * 获取调整历史
     */
    @GetMapping("/api/pools/{name}/adjustments")
    @ResponseBody
    @CrossOrigin(origins = "*")
    public List<String> getAdjustmentHistory(@PathVariable String name) {
        return adjustmentHistory.getOrDefault(name, new ArrayList<>());
    }
    
    /**
     * 手动调整线程池参数
     */
    @PostMapping("/api/pools/{name}/adjust")
    @ResponseBody
    @CrossOrigin(origins = "*")
    public Map<String, Object> adjustThreadPool(
            @PathVariable String name,
            @RequestParam(required = false) Integer coreSize,
            @RequestParam(required = false) Integer maxSize,
            @RequestParam(required = false) Integer queueCapacity) {
        
        DynamicThreadPoolExecutor executor = threadPoolMap.get(name);
        if (executor == null) {
            return Collections.singletonMap("error", "Thread pool not found: " + name);
        }
        
        Map<String, Object> result = new HashMap<>();
        try {
            if (coreSize != null) {
                executor.setCorePoolSize(coreSize);
                addAdjustmentHistory(name, "手动调整核心线程数: " + coreSize);
            }
            if (maxSize != null) {
                executor.setMaximumPoolSize(maxSize);
                addAdjustmentHistory(name, "手动调整最大线程数: " + maxSize);
            }
            if (queueCapacity != null && executor.getQueue() instanceof cn.sunyblog.tool.threadpool.queue.DynamicBlockingQueue) {
            ((cn.sunyblog.tool.threadpool.queue.DynamicBlockingQueue<?>) executor.getQueue()).setCapacity(queueCapacity);
                addAdjustmentHistory(name, "手动调整队列容量: " + queueCapacity);
            }
            
            result.put("success", true);
            result.put("message", "调整成功");
            result.put("newStatus", executor.getCurrentMetrics());
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 获取线程池详细信息
     */
    @GetMapping("/api/pools/{name}/details")
    @ResponseBody
    public Map<String, Object> getThreadPoolDetails(@PathVariable String name) {
        DynamicThreadPoolExecutor executor = threadPoolMap.get(name);
        if (executor == null) {
            return Collections.singletonMap("error", "Thread pool not found: " + name);
        }
        
        Map<String, Object> details = new HashMap<>();
        details.put("name", name);
        details.put("corePoolSize", executor.getCorePoolSize());
        details.put("maximumPoolSize", executor.getMaximumPoolSize());
        details.put("activeCount", executor.getActiveCount());
        details.put("poolSize", executor.getPoolSize());
        details.put("queueSize", executor.getQueue().size());
        details.put("queueRemainingCapacity", executor.getQueue().remainingCapacity());
        details.put("completedTaskCount", executor.getCompletedTaskCount());
        details.put("taskCount", executor.getTaskCount());
        details.put("isShutdown", executor.isShutdown());
        details.put("isTerminated", executor.isTerminated());
        
        return details;
    }
}